package ppOO;

public class Program extends General {

   public static void main(String[] args) {
      // example3_7();
      assignment2();

   }

   private static void assignment2() {

      double[][] weights_layer1 = new double[][] {
            {
                  -0.7402, -0.0612, -0.3258, 0.5886,
                  0.0571, 0.2040, 0.3082, 0.4963, -0.8324,
                  0.8267, 0.6516, 0.9923, -0.1146, 0.9238,
                  0.5498, 0.7374, 0.2004 },
            {
                  0.1376, -0.9762, -0.6756, -0.3776,
                  -0.6687, -0.4741, 0.3784, -0.0989,
                  -0.5420, -0.6952, 0.0767, -0.8436,
                  -0.7867, -0.9907, 0.6346, -0.8311,
                  -0.4803 } };

      double[][] weights_layer2 = {
            {
                  0.5144, 0.1356, 0.0616 }, {
                  0.5075, -0.8483, 0.5583 }, {
                  -0.2391, -0.8921, 0.8680 } };

      double[][] input = new double[][] {
            {
                  1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1,
                  -1, -1, 1, -1, -1, -1 },
            {
                  1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1,
                  1, 1, 1, -1, -1 },
            {
                  1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1,
                  1, -1, -1, -1, -1 },
            {
                  -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1,
                  -1, -1, -1, 1, -1, -1 },
            {
                  -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1,
                  -1, 1, 1, 1, -1 },
            {
                  -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1,
                  -1, 1, -1, -1, -1 } };

      double[][] desired = new double[][] {
            {
                  1, -1, -1 }, {
                  -1, 1, -1 }, {
                  -1, -1, 1 }, {
                  1, -1, -1 }, {
                  -1, 1, -1 }, {
                  -1, -1, 1 } };

      double[] output;
      double[] cycleError = new double[600 / input.length + 1];

      final double learningRate = 0.2;

      NeuralNetwork nnet = new NeuralNetwork(learningRate);
      nnet.addLayer(2, weights_layer1);
      nnet.addLayer(3, weights_layer2);

      nnet.setNetworkInput(input[0], desired[0]);

      nnet.finalise();

      nnet.calcNetworkOutput();
      long j = 0;
      for (long i = 0; i < 601; i++) {
         System.out
               .println("\nIteration: "
                     + i
                     + " )=========================================================\n");
         System.out
               .println("INPUT:   "
                     + printArray(input[(int) (i % input.length)]));
         System.out
               .println("DESIRED: "
                     + printArray(desired[(int) (i % input.length)]));
         output = nnet.train(
               input[(int) (i % input.length)],
               desired[(int) (i % input.length)]);
         nnet.printNeuralNetwork();
         System.out
               .println("OUTPUT:  "
                     + printArray(output)
                     + "\tDESIRED:  "
                     + printArray(desired[(int) (i % input.length)]));

         cycleError[(int) j] = nnet.getAccumulatedError();
         if ((i % input.length) == 0) {
            nnet.resetNetworkCycleError();
            j++;
         }
      }
      System.out
            .println("=============================================================");
      System.out.println("Finished Training");
      nnet.printNeuralNetwork();
      System.out
            .println("=============================================================");
      System.out.println("Cycle Error");
      System.out
            .println("=============================================================");
      for (double i : cycleError) {
         System.out.println(i);
      }
      System.out
            .println("=============================================================");

   }

   private static void example3_7() {
      double[][] weights_layer1 = new double[][] {
            {
                  -6.9938, 6.6736, 1.5555 }, {
                  -4.2812, 3.9127, 3.6233 } };
      double[][] weights_layer2 = new double[][] { {
            -0.8568, 0.3998, -1.0702 } };

      double[][] input = new double[][] {
            {
                  0, 0, -1 }, {
                  0, 1, -1 }, {
                  1, 1, -1 }, {
                  1, 0, -1 } };
      double[][] desired = new double[][] {
            { -1 }, { 1 }, { -1 }, { 1 } };
      double[] output;

      final double learningRate = 0.1;

      NeuralNetwork nnet = new NeuralNetwork(learningRate);

      nnet.addLayer(2, weights_layer1);
      nnet.addLayer(1, weights_layer2);

      nnet.setNetworkInput(input[0], desired[0]);

      nnet.finalise();

      nnet.calcNetworkOutput();

      for (int i = 0; i < 1; i++) {
         System.out
               .println("\n"
                     + i
                     + " )=========================================================\n");
         System.out.println("INPUT:   "
               + printArray(input[i % 4]));
         System.out.println("DESIRED: "
               + printArray(desired[i % 4]));
         output = nnet.train(input[i % 4], desired[i % 4]);
         nnet.printNeuralNetwork();
         System.out.println("OUTPUT:  "
               + printArray(output) + "\tDESIRED:  "
               + printArray(desired[i % 4]));
      }
      System.out
            .println("=============================================================");
      System.out.println("Finished Training");
      nnet.printNeuralNetwork();

   }

}
